﻿// registers the GMap2 class with Microsoft Ajax framework
google.maps.Map2.registerClass('google.maps.Map2');

var AAASTATUS_LOADING = 1;
var AAASTATUS_OK = 0;
var AAASTATUS_ERROR = -1;

/*
    AAAMap is a GMap2 subclass that introduces some useful features. It contains:
    - an array of AAATrip objects; each element represents a non-editable trip shown on the map
    - a single editable trip (i.e. an editable AAATrip object) shown on the map
    - an array of 'explorators'. An explorator is a GMarker object that can explore the map
      by dragging and clicking on it
    - a new Virtual Earth map type that can be accessed from the usual menu in the top right corner
*/
MapControl2.AAAMap = function(mapDiv, options)
{
    // invokes the base class constructor with arguments
    var args = new Array();
    args.push(mapDiv);
    if (options)
    {
        args.push(options);
    }
    MapControl2.AAAMap.initializeBase(this, args);  
    
    this._trips = new Array();      // this is the array of non-editable trips
    this._selectedTripIndex = -1;   // index of current selected non-editable trip
    this._menu = new AAAMenu(mapDiv, this);
    this._mapDiv = mapDiv;
    this._mapDiv.loapaths = new Array();
    this._isEditable = false;
    this._editableTrip = null;
    this._listVehicles = new Array();
    this._subRouteHandler = new Array();
    this._explorators = new Array();
    this._myCtrl = null;
    this._normalProj = G_NORMAL_MAP.getProjection();
    this._divCenter = new GPoint(mapDiv.clientWidth/2, mapDiv.clientHeight/2);
    
    // event listening (mouse move disabled because of virtual earth conflicts)
    GEvent.addListener(this, 'dragstart', GEvent.callback(this._menu, this._menu.hideMenu));    
    GEvent.addListener(this, 'singlerightclick', GEvent.callback(this, this._mapRightClick));
    GEvent.addListener(this, 'maprightclick', GEvent.callback(this, this._onlyMapRightClick));
    
    // mousemove handling
    this._divCenter = {'x': Math.floor(mapDiv.clientWidth/2), 'y': Math.floor(mapDiv.clientHeight/2)};
    this._mouseMoveObj = {'latlng':null, 'absPixel': new google.maps.Point(0, 0)};
    this._mouseMovePixel = {'x':0, 'y':0};
    this._normalProj = G_NORMAL_MAP.getProjection();
    
    //Virtual Earth Integration
    var ve_layer = new GTileLayer(new GCopyrightCollection(''),1,19); 
    var ve_map_type = new GMapType([ve_layer], 
			G_SATELLITE_MAP.getProjection(), "Virtual Earth",{errorMessage:"No MS VE Data"}); 
	ve_layer.getTileUrl = function(a, b){ 							
		var tile_string = MapControl2.AAAUtils.tileEncoding(a.x,a.y,b);				
		s = 'http://a' 
		s += tile_string.substring(tile_string.length-1, tile_string.length); 
		s += '.ortho.tiles.virtualearth.net/tiles/a' 
		s += tile_string; 
		s += '.jpeg?g=1'; 
		return s; 
	};
	ve_layer.getCopyright = function(a,b) {return 'Microsoft Virtual Earth';} 
	ve_map_type.getTextColor = function() {return "#FFFFFF";};
	this.addMapType(ve_map_type);
};

MapControl2.AAAMap.prototype = {
    
    // -------------------------- private functions ------------------------------------------------
    // centers the map over <aaaTrip>
    _centerOnTrip: function(aaaTrip)
    {
        var tripBounds = aaaTrip.getBounds();
        this.setCenter(tripBounds.getCenter());
        this.setZoom(this.getBoundsZoomLevel(tripBounds));
    },
    
    _fillMouseMoveObj: function(pixel)
    {
        var absCenter = this._normalProj.fromLatLngToPixel(this.getCenter(), this.getZoom());
        this._mouseMoveObj.absPixel.x = absCenter.x - (this._divCenter.x - pixel.x);
        this._mouseMoveObj.absPixel.y = absCenter.y - (this._divCenter.y - pixel.y);
        this._mouseMoveObj.latlng = this._normalProj.fromPixelToLatLng(this._mouseMoveObj.absPixel, this.getZoom());
    },
    // ------------------------------------------------------------------------------------------
    
    // --------------- event handlers -----------------------------------------------------------
    _mapRightClick: function(point, src, overlay){
        var ok = true;
        if (overlay)
            ok = (overlay == this.getContainer());
        if (ok)
            GEvent.trigger(this, 'maprightclick', point);
    },
    
    _onlyMapRightClick: function(point){
        this._menu.showMenu(point, 0);
    },
    
    _mouseUpOnMap: function(e)
    {
        if (!e) var e = window.event;
        if(e.button == 2 && (!this._menu.polymenuDiv.click) )
        {        
            var f = Function.createDelegate(this, showM);
            f(e, 0);
        }else 
        {
            this._menu.polymenuDiv.click = false;
        }
    },
    
    _moveOnMap: function(e)
    {
        var pixel = MapControl2.AAAUtils.fromEventToDivPixel(e, this._mouseMoveObj, this.getContainer().id);
        
        // computing latlng..
        var absCenter = this._normalProj.fromLatLngToPixel(this.getCenter(), this.getZoom());
        this._mouseMoveObj.absPixel.x = absCenter.x - (this._divCenter.x - pixel.x);
        this._mouseMoveObj.absPixel.y = absCenter.y - (this._divCenter.y - pixel.y);
        this._mouseMoveObj.latlng = this._normalProj.fromPixelToLatLng(this._mouseMoveObj.absPixel, this.getZoom());
        
        GEvent.trigger(this, 'map_mousemove', this._mouseMoveObj);
    },
    
    _exploratorDragEnd: function(explorator){
        explorator._dontshow = true;
        explorator.checkPosition( function(){
                    explorator._tabs[0].content = '<b>Location</b>:' + explorator._geoloc.address;
                    explorator._dontshow = false;
                    GEvent.trigger(explorator, 'exploration_performed', explorator);});
    },
    // ------------------------------------------------------------------------------------------
    
    // -------------------------- properties ----------------------------------------------------
    setEditable: function(value)
    {
        this._isEditable = value;
    },
    isEditable: function()
    {
        return (this._isEditable);
    },
    getEditableTrip: function()
    {
        return this._editableTrip;
    },
    setEditableTrip: function(value)
    {
        this.clearEditableTrip();
        this._editableTrip = value;
        this._centerOnTrip(value);
    },
    clearEditableTrip: function(){
        if (this._editableTrip != null){
            this._editableTrip.clear();
            this._editableTrip = null;
        }
    },
    getParentDiv: function()
    {
        return (this._mapDiv);
    },
    getSelectedTrip: function()
    {
        if (this._selectedTripIndex !== -1)
            return (this._trips[this._selectedTripIndex]);
        return null;
    },
    // ------------------------------------------------------------------------------------------
   
    // -------------------------- public functions ----------------------------------------------
    // Adds a new non-editable AAATrip on the map
    addTrip: function(trip)
    {
        // aggiunge il viaggio alla lista...
        this._trips.push(trip);
        this._centerOnTrip(trip);
    },
    
    clearUneditableTrips : function()
    {
        while( this._trips.length > 0 )
        {
            var atrip = this._trips.pop();
            atrip.clear();
        }
    },
    
    checkResize: function(){
        this._divCenter.x = this._mapDiv.clientWidth/2;
        this._divCenter.y = this._mapDiv.clientHeight/2;
        MapControl2.AAAMap.callBaseMethod(this, 'checkResize', []);
    },
    
    // fromDivPixelToLatLng GMap2 method is incorrect
    fromDivPixelToLatLng: function(px){
        var absCenter = this._normalProj.fromLatLngToPixel(this.getCenter(), this.getZoom());
        var absPoint = new GPoint(absCenter.x - (this._divCenter.x - px.x), 
                                  absCenter.y - (this._divCenter.y - px.y));
        return (this._normalProj.fromPixelToLatLng(absPoint, this.getZoom()));
    },
   
    // Adds a new explorator to the map at the given coordinates (<latlng>); the explorator's
    // icon is identified by <type>, which can be one of the registered AAAMarker types.
    // The created explorator is returned, in order to deregister it using removeExplorator
    addExplorator: function(latlng, type) {
        var gloc = MapControl2.AAAUtils.createGeoLocFromLatLng(latlng);
        var explorator = new MapControl2.AAAMarker(gloc, false, type, '...');
        explorator._isExploring = true;
        GEvent.addListener(explorator, 'dragend2', GEvent.callback(this, this._exploratorDragEnd));
        explorator._tabs[0].label = 'Exploration Info';
        this._explorators.push(explorator);
        this.addOverlay(explorator);
        this._exploratorDragEnd(explorator);
        return explorator;
    },
    
    // removes a map explorator
    removeExplorator: function(explorator){
        var index = -1;
        for (var i=0; i<this._explorators.length; i++){
            if (this._explorators[i] == explorator){
                index = i; break;
            }
        }
        if (index != -1){
            this.removeOverlay(explorator);
            this._explorators.splice(index, 1);
        }
    },
    
    // removes all map explorators
    clearExplorators: function(){
        for (var i=0; i<this._explorators.length; i++){
            this.removeOverlay(this._explorators[i]);
        }
        this._explorators = new Array();
    },
    
    // transform a div pixel to a GLatLng object 
    //(this function is needed because of Virtual Earth conflicts)
    fromPixelToLatLng: function(pixel)
    {
        this._fillMouseMoveObj(pixel);
        return this._mouseMoveObj.latlng;
    },
    
    // makes this object "visitable"
    accept: function(visitor)
    {
        visitor.visit(this, MapControl2.AAAMAP_ELEMENT);
    },
    
    setPassengerDeparture: function(userId, depGeoLoc, radius)
    {
        if (this._isEditable)
        {
            if(this._editableTrip != null)
            {
                var existingStage = this._editableTrip._markers;
                for(var i=0; i<existingStage.length; i++)
                    existingStage[i].setLocked(true);
            }
            else
                return; // è inutile settare i passeggeri da caricare se non c'è il viaggio dove appenderli
        }
        
        if(this._passengerDep != null)
        {
            google.maps.Event.clearInstanceListeners(this._passengerDep);
            this.removeOverlay(this._passengerDep);
        }
        this._passengerDep = new MapControl2.AAAPassengerMarker(userId, depGeoLoc, radius, true, !this._isEditable);
        this.addOverlay(this._passengerDep);
    },
    
    setPassengerArrive: function(userId, arrGeoLoc, radius)
    {
        if (this._isEditable)
        {
            if(this._editableTrip != null)
            {
                var existingStage = this._editableTrip._markers;
                for(var i=0; i<existingStage.length; i++)
                    existingStage[i].setLocked(true);
            }
            else
                return; // è inutile settare i passeggeri da caricare se non c'è il viaggio dove appenderli
        }
        
        
        if(this._passengerArr != null)
        {
            google.maps.Event.clearInstanceListeners(this._passengerArr);
            this.removeOverlay(this._passengerArr);
        }
        this._passengerArr = new MapControl2.AAAPassengerMarker(userId, arrGeoLoc, radius, false, !this._isEditable);
        this.addOverlay(this._passengerArr);
    },
    
    setPassengerPositions: function(userId, depGeoLoc, depRadius, arrGeoLoc, arrRadius)
    {
        this.setPassengerDeparture(userId, depGeoLoc, depRadius);
        this.setPassengerArrive(userId, arrGeoLoc, arrRadius);       
        this._menu.enablePassengerMenuVoices();
    },
    
    // if is passed only first parameter this means stage marker where passenger is getting in
    // else first parameter means index index  and relative subroute index where insert 
    // new stage to getting in the passenger
    gettingInPassenger: function(routeIndex, subRouteIndex)
    {
        if (this._editableTrip._status == AAASTATUS_LOADING)
            return;
            
        if(this._passengerDep != null)
        {
            if(subRouteIndex != null)
                this._passengerDep.insertAsNewStage(routeIndex,subRouteIndex);
            else
                this._passengerDep.overlapToExistingStage(this._editableTrip._markers[routeIndex]);
        }  
    },
    
    // returns true iff there is a passenger to be taken and this passenger is properly attached to the trip
    isPassengerAttached: function(){
        if (this._passengerDep && this._passengerArr)
            return (this._passengerDep._attached && this._passengerArr._attached);
        return false;
    },
    
    // if is passed only first parameter, this means stage marker index where passenger is getting off,
    // else first parameter means index index  and relative subroute index where insert 
    // new stage to getting off the passenger
    gettingOffPassenger: function(routeIndex, subRouteIndex)
    {
        if (this._editableTrip._status == AAASTATUS_LOADING)
            return;
   
        if(this._passengerArr != null)
        {
            if(subRouteIndex != null)
                this._passengerArr.insertAsNewStage(routeIndex,subRouteIndex);
            else
                this._passengerArr.overlapToExistingStage(this._editableTrip._markers[routeIndex]);
        }    
    }
    // -------------------------------------------------------------------------------
};

MapControl2.AAAMap.registerClass('MapControl2.AAAMap', google.maps.Map2);
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
